package org.alex.spring.core.context;

import lombok.Data;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * Bean定义信息
 */
@Data
public class BeanDefinition {
    /**
     * 全局唯一Bean名称
     */
    private String name;

    /**
     * Bean声明的类型
     */
    private Class<?> beanClass;

    /**
     * Bean的实例
     */
    private Object instance = null;

    /**
     * Bean的构造方法
     */
    private Constructor<?> constructor;

    /**
     * 工厂方法名称
     */
    private String factoryName;

    /**
     * 工厂方法
     */
    private Method factoryMethod;

    /**
     * Bean的顺序
     */
    private int order;

    /**
     * 是否标识为@Primary
     */
    private boolean primary;

    /**
     * 初始化方法名称
     */
    private String initMethodName;

    /**
     * 销毁方法名称
     */
    private String destroyMethodName;

    /**
     * 初始化方法
     */
    private Method initMethod;

    /**
     * 销毁方法
     */
    private Method destroyMethod;

    public BeanDefinition(String name, Class<?> beanClass, Constructor<?> constructor, int order, boolean primary, String initMethodName,
                          String destroyMethodName, Method initMethod, Method destroyMethod) {
        this.name = name;
        this.beanClass = beanClass;
        this.constructor = constructor;
        this.factoryName = null;
        this.factoryMethod = null;
        this.order = order;
        this.primary = primary;
        constructor.setAccessible(true);
        setInitAndDestroyMethod(initMethodName, destroyMethodName, initMethod, destroyMethod);
    }

    public BeanDefinition(String name, Class<?> beanClass, String factoryName, Method factoryMethod, int order, boolean primary, String initMethodName,
                          String destroyMethodName, Method initMethod, Method destroyMethod) {
        this.name = name;
        this.beanClass = beanClass;
        this.constructor = null;
        this.factoryName = factoryName;
        this.factoryMethod = factoryMethod;
        this.order = order;
        this.primary = primary;
        factoryMethod.setAccessible(true);
        setInitAndDestroyMethod(initMethodName, destroyMethodName, initMethod, destroyMethod);
    }

    private void setInitAndDestroyMethod(String initMethodName, String destroyMethodName, Method initMethod, Method destroyMethod) {
        this.initMethodName = initMethodName;
        this.destroyMethodName = destroyMethodName;
        if (initMethod != null) {
            initMethod.setAccessible(true);
        }
        if (destroyMethod != null) {
            destroyMethod.setAccessible(true);
        }
        this.initMethod = initMethod;
        this.destroyMethod = destroyMethod;
    }
}
